﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Kugar.Core.ExtMethod;
using Kugar.Core.Web;
using Kugar.UI.Web.AdminLTE.Authentications;
using Kugar.UI.Web.AdminLTE.Filters;
using Kugar.UI.Web.AdminLTE.Interfaces;
using Kugar.UI.Web.AdminLTE.PageControls;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Razor;

#if NETCOREAPP3_0
  using Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation;  
#endif

using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using HttpContext = Kugar.Core.Web.HttpContext;

namespace Kugar.UI.Web.AdminLTE.Helpers
{
    public static class GlobalConfigurationHelper
    {
        internal static Dictionary<string,IAdminLoginManager> _cache=new Dictionary<string, IAdminLoginManager>(StringComparer.CurrentCultureIgnoreCase);

        /// <summary>
        /// 启用AdminLTEUI组件
        /// </summary>
        /// <param name="services"></param>
        public static void UseAdminLTE(this IServiceCollection services,bool registerOldAuthorize=true)
        {
            services.AddScoped(typeof(AdminLTEUI));

            var embeddedProvider = new EmbeddedFileProvider(typeof(AdminLTEElementBase).Assembly, "Kugar.UI.Web.AdminLTE");

#if NETCOREAPP3_0
            services.Configure<MvcRazorRuntimeCompilationOptions>(options => {
                options.FileProviders.Clear();
                options.FileProviders.Add(embeddedProvider);
            });
#endif

#if NETCOREAPP2_1
            services.Configure<RazorViewEngineOptions>(options =>
            {
                options.FileProviders.Add(embeddedProvider);
            });
#endif
            

            if (registerOldAuthorize)
            {
                
                //services.AddAuthorization(options =>
                //    {
                //        options.AddPolicy("AdminLteDefaultAdminCheck", policy =>
                //            policy.Requirements.Add(new AdminAuthorityRequirement()));
                //    })
                //    ;
                //services.AddSingleton<IAuthorizationHandler, AdminAuthorityPolicyHandler>();

            }
            //else
            {
                services.AddScoped<IAdminLoginManager>(x =>
                {
                    if (HttpContext.Current.GetRouteData().Values.TryGetValue("authenticationType", out var scheme))
                    {
                        if (_cache.TryGetValue(scheme.ToStringEx(), out var handler))
                        {
                            return handler;
                        }
                    }

                    return null;

                });
            }
            


            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                // Set a short timeout for easy testing.
                //options.Cookie.SecurePolicy = CookieSecurePolicy.None;
                options.Cookie.Name = ".NetEscapades.Session";
                options.IdleTimeout = TimeSpan.FromMinutes(15);
                options.Cookie.HttpOnly = false;
                
#if NETCOREAPP2_1
                options.CookiePath = "/";
#endif
#if NETCOREAPP3_0
                options.Cookie.Path = "/";
#endif

                //options.Cookie.Expiration=TimeSpan.FromDays(15);
                options.Cookie.SameSite = SameSiteMode.Lax;
            });


        }

        /// <summary>
        /// 是否使用内嵌的静态资源
        /// </summary>
        /// <param name="app"></param>
        public static void UseAdminLTEStaticFile(this IApplicationBuilder app)
        {
            app.UseSession();

            var embeddedProvider = new EmbeddedFileProvider(typeof(AdminLTEElementBase).Assembly, "Kugar.UI.Web.AdminLTE");

            //AdminLTEUI.InternalFileMD5=new ResourceFileMD5();
            AdminLTEUI.InternalFileMD5.webui_ctrl_all_plugins_js =
                calcStaticFileMD5(embeddedProvider, "/Content/lib/webui_ctrl/all_plugins.js");

            AdminLTEUI.InternalFileMD5.WebUIJS_js =
                calcStaticFileMD5(embeddedProvider, "/Content/js/WebUIJS.js");

            AdminLTEUI.InternalFileMD5.WebUIJS_inner_js =
                calcStaticFileMD5(embeddedProvider, "/Content/js/WebUIJS.inner.js");

            AdminLTEUI.InternalFileMD5.WebUIJS_iframe_js =
                calcStaticFileMD5(embeddedProvider, "/Content/js/WebUIJS.iframe.js");

            AdminLTEUI.InternalFileMD5.webui_ctrl_all_plugins_css =
                calcStaticFileMD5(embeddedProvider, "/Content/lib/webui_ctrl/all_plugins.css");

            AdminLTEUI.InternalFileMD5.AdminLTEUICSS_css =
                calcStaticFileMD5(embeddedProvider, "/Content/css/AdminLTEUICSS.css");

            AdminLTEUI.InternalFileMD5.AdminLTEUICSS_inner_css =
                calcStaticFileMD5(embeddedProvider, "/Content/css/AdminLTEUICSS.inner.css");

            AdminLTEUI.InternalFileMD5.AdminLTEUI_iframe_css =
                calcStaticFileMD5(embeddedProvider, "/Content/css/AdminLTEUI.iframe.css");

            app.UseStaticFiles(new StaticFileOptions
                {
                    FileProvider = embeddedProvider,
                    RequestPath = new PathString("/adminltebase"),
                    OnPrepareResponse = (context) =>
                    {
                        var headers = context.Context.Response.GetTypedHeaders();
                        headers.CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
                        {
                            Public = true,
                            MaxAge = TimeSpan.FromDays(365),

                        };
                    }
                });


            //options.AddPolicy("Over21", policy => policy.Requirements.Add(new MinimumAgeRequirement(21)));
        }

        public static AuthenticationBuilder AddAdminLTECookie(this AuthenticationBuilder builder,
            string authenticationScheme,
            string displayName,
            Action<AdminLteAuthenticationOptions> configureOptions)
        {
            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<AdminLteAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
            return builder.AddScheme<AdminLteAuthenticationOptions, AdminLteAuthenticationHandler>(authenticationScheme, displayName,option=>
            {
                option.SchemeName = authenticationScheme;
                configureOptions?.Invoke(option);
                _cache.Add(authenticationScheme, option.LoginManager);
            });
        }

        public static AuthenticationBuilder AddAdminLTECookie(this AuthenticationBuilder builder,
            string authenticationScheme,
            Action<AdminLteAuthenticationOptions> configureOptions=null)
        {
            return AddAdminLTECookie(builder, authenticationScheme, authenticationScheme, configureOptions);

            //builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<AdminLteAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
            //return builder.AddScheme<AdminLteAuthenticationOptions, AdminLteAuthenticationHandler>(authenticationScheme, authenticationScheme, option =>
            //{
            //    option.SchemeName = authenticationScheme;
            //    configureOptions?.Invoke(option);
            //    _cache.Add(authenticationScheme,option.LoginManager);

            //});
        }

        public static AuthenticationBuilder AddAdminLTECookie(this AuthenticationBuilder builder,
            string authenticationScheme,IAdminLoginManager loginManager)
        {
            

            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<AdminLteAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
            return builder.AddScheme<AdminLteAuthenticationOptions, AdminLteAuthenticationHandler>(authenticationScheme, authenticationScheme, option =>
            {
                option.SchemeName = authenticationScheme;
                option.LoginManager = loginManager;
                _cache.Add(authenticationScheme,loginManager);
            });
        }

        /// <summary>
        /// 注册一个默认的登录处理器,用于兼容老的代码
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static AuthenticationBuilder AddDefaultAdminLTECookie(this AuthenticationBuilder builder)
        {
            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<AdminLteAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
            return builder.AddScheme<AdminLteAuthenticationOptions, AdminLteAuthenticationHandler>("default", "default", option =>
            {
                option.SchemeName = "default";
            });
        }

        public static string calcStaticFileMD5(EmbeddedFileProvider provider, string filePath)
        {
            using (var file = provider.GetFileInfo(filePath).CreateReadStream())
            {
                var md5 = file.ReadToEnd(Encoding.UTF8).MD5_32(true);

                return md5.Left(8);
            }
        }
    }
}
